package com.ht.api.db.util;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.sql.DataSource;

import com.ht.api.db.Db;
import com.ht.api.db.Entity;
import com.ht.api.db.exception.HtException;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

/**
 * 花田工具类
 * @author asq
 * @createTime 2025年1月3日 18:22:18
 */
public class HtUtil {
    private static final Pattern ARRAY_PATTERN = Pattern.compile("(.+?)\\[(\\d+)\\]\\.(.+)"); // 匹配数组字段
    private static final Pattern NESTED_PATTERN = Pattern.compile("(.+?)\\.(.+)"); // 匹配嵌套字段
	
	/**
	 * 获取String型唯一的主键ID
	 * @return
	 */
	public static String getId() {
		return String.valueOf(IdUtil.getSnowflake(1, 1).nextId());
	}

	/**
	 * 获取long型唯一主键ID
	 * @return
	 */
	public static long getIdLong() {
		return IdUtil.getSnowflake(1, 1).nextId();
	}

	/**
	 * 使用摘要算法，将字符串转唯一主键
	 * @param uniqueString
	 * @return
	 */
	public static String uniqueStrToNum(String uniqueString) {
		try {
			if (uniqueString == null) {
				return "-1";
			}
			// 获取SHA-256实例
			MessageDigest md = MessageDigest.getInstance("SHA-256");
			byte[] hashBytes = md.digest(uniqueString.getBytes());

			// 取前16字节生成BigInteger
			byte[] truncatedHashBytes = new byte[16];
			System.arraycopy(hashBytes, 0, truncatedHashBytes, 0, 16);

			BigInteger bigInt = new BigInteger(1, truncatedHashBytes); // 1 表示正数

			// 限制在 MySQL BIGINT 的正数范围内
			BigInteger maxBigInt = new BigInteger("9223372036854775807"); // MySQL BIGINT 最大正数
			return bigInt.mod(maxBigInt).toString(); // 取模以确保在范围内
		} catch (NoSuchAlgorithmException e) {
		}
		return "-1";
	}

	/**
	 * 测试某个字段是否是预期的类型
	 * @param json
	 * @param field
	 * @param clazz
	 * @return
	 */
	public static boolean canConvertToClass(JSONObject json, String field, Class<?> clazz) {
		try {
			if (json.containsKey(field)) {
				Object value = json.get(field);
				if (value instanceof JSONObject) {
					// 尝试转换
					JSONUtil.toBean((JSONObject) value, clazz);
					return true;
				}
			}
			return false;
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 检查 JSON 对象是否包含指定路径
	 * @param json
	 * @param path
	 * @return
	 */
	public static boolean hasPath(JSONObject json, String path) {
		if (json == null || StrUtil.isBlank(path)) {
			return false;
		}

		try {
			return json.getByPath(path) != null;
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 格式化日期
	 * @param timeStr
	 * @return
	 */
	public static String formatTimeString(String timeStr) {
		// 处理空值
		if (timeStr == null || timeStr.trim().isEmpty()) {
			return "";
		}

		try {
			timeStr = timeStr.trim();

			// 处理时间戳（秒级和毫秒级）
			if (timeStr.matches("\\d+")) {
				long timestamp;
				if (timeStr.length() == 13) {
					// 毫秒级时间戳
					timestamp = Long.parseLong(timeStr);
				} else if (timeStr.length() == 10) {
					// 秒级时间戳
					timestamp = Long.parseLong(timeStr) * 1000;
				} else {
					return "-1";
				}
				Date date = new Date(timestamp);
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				return sdf.format(date);
			}

			// 处理标准格式 2024-03-21 10:15:30 或 2024/03/21 10:15:30
			if (Pattern.matches("^\\d{4}[-/]\\d{2}[-/]\\d{2}\\s\\d{2}:\\d{2}:\\d{2}$", timeStr)) {
				timeStr = timeStr.replace("/", "-");
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				Date date = sdf.parse(timeStr);
				return sdf.format(date);
			}

			// 处理紧凑格式 20240321101530
			if (Pattern.matches("^\\d{14}$", timeStr)) {
				SimpleDateFormat inputFormat = new SimpleDateFormat("yyyyMMddHHmmss");
				SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				Date date = inputFormat.parse(timeStr);
				return outputFormat.format(date);
			}

			return timeStr;

		} catch (Exception e) {
			return timeStr;
		}
	}

	/**
	 * 还原扁平化结构的json对象为标准结构的json对象
	 * @param originalNode 原始 JSON 对象
	 * @return 转换后的 JSON 对象
	 */
	public static JSONObject revertJson(JSONObject originalNode) {
		JSONObject transformedNode = new JSONObject();
		transformNode(originalNode, transformedNode);
		return transformedNode;
	}

	/**
     * 递归处理 JSON 节点
     *
     * @param sourceNode 原始节点
     * @param targetNode 目标节点
     */
    private static void transformNode(JSONObject sourceNode, JSONObject targetNode) {
        // 用于存储数组数据的 Map
        Map<String, Map<Integer, JSONObject>> arrayMap = new HashMap<>();

        // 遍历原始节点的字段
        for (Map.Entry<String, Object> entry : sourceNode.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();

            Matcher arrayMatcher = ARRAY_PATTERN.matcher(key);
            Matcher nestedMatcher = NESTED_PATTERN.matcher(key);

            if (arrayMatcher.matches()) {
                // 如果是数组字段（如 msgmenu.list[0].type）
                String arrayName = arrayMatcher.group(1); // 数组名称（如 msgmenu.list）
                int index = Integer.parseInt(arrayMatcher.group(2)); // 数组索引（如 0）
                String field = arrayMatcher.group(3); // 剩余字段（如 type）

                // 获取或创建对应的数组 Map
                Map<Integer, JSONObject> arrayItemMap = arrayMap.computeIfAbsent(arrayName, k -> new HashMap<>());
                JSONObject arrayItem = arrayItemMap.computeIfAbsent(index, k -> new JSONObject());

                // 递归处理剩余字段
                setNestedField(arrayItem, field, value);
            } else if (nestedMatcher.matches()) {
                // 如果是嵌套字段（如 msgmenu.head_content）
                String parentKey = nestedMatcher.group(1); // 父字段名称（如 msgmenu）
                String childKey = nestedMatcher.group(2); // 子字段名称（如 head_content）

                // 获取或创建父节点
                JSONObject parentNode = targetNode.getJSONObject(parentKey);
                if (parentNode == null) {
                    parentNode = new JSONObject();
                    targetNode.set(parentKey, parentNode);
                }

                // 递归处理子字段
                setNestedField(parentNode, childKey, value);
            } else {
                // 普通字段直接放入目标节点
                targetNode.set(key, value);
            }
        }

        // 将数组 Map 转换为 JSONArray
        for (Map.Entry<String, Map<Integer, JSONObject>> entry : arrayMap.entrySet()) {
            String arrayName = entry.getKey();
            Map<Integer, JSONObject> arrayItemMap = entry.getValue();

            JSONArray arrayItems = new JSONArray(arrayItemMap.size());
            arrayItemMap.keySet().stream().sorted().forEach(index -> arrayItems.add(index, arrayItemMap.get(index)));
            targetNode.set(arrayName, arrayItems);
        }
    }

    /**
     * 递归设置嵌套字段
     *
     * @param parentNode 父节点
     * @param nestedKey  嵌套键（如 list[0].type）
     * @param value      字段值
     */
    private static void setNestedField(JSONObject parentNode, String nestedKey, Object value) {
        Matcher arrayMatcher = ARRAY_PATTERN.matcher(nestedKey);
        Matcher nestedMatcher = NESTED_PATTERN.matcher(nestedKey);

        if (arrayMatcher.matches()) {
            // 如果嵌套键是数组字段（如 list[0].type）
            String arrayName = arrayMatcher.group(1); // 数组名称（如 list）
            int index = Integer.parseInt(arrayMatcher.group(2)); // 数组索引（如 0）
            String field = arrayMatcher.group(3); // 剩余字段（如 type）

            // 获取或创建对应的数组 Map
            JSONArray arrayItems = parentNode.getJSONArray(arrayName);
            if (arrayItems == null) {
                arrayItems = new JSONArray();
                parentNode.set(arrayName, arrayItems);
            }

            // 确保数组大小足够
            while (arrayItems.size() <= index) {
                arrayItems.add(new JSONObject());
            }

            // 递归处理剩余字段
            setNestedField(arrayItems.getJSONObject(index), field, value);
        } else if (nestedMatcher.matches()) {
            // 如果嵌套键是普通嵌套字段（如 click.id）
            String parentKey = nestedMatcher.group(1); // 父字段名称（如 click）
            String childKey = nestedMatcher.group(2); // 子字段名称（如 id）

            // 获取或创建父节点
            JSONObject parent = parentNode.getJSONObject(parentKey);
            if (parent == null) {
                parent = new JSONObject();
                parentNode.set(parentKey, parent);
            }

            // 递归处理子字段
            setNestedField(parent, childKey, value);
        } else {
            // 如果没有点号或数组，直接设置字段
            parentNode.set(nestedKey, value);
        }
    }
    
    /**
     * 新增关联日志内容
     * @param ds
     * @param relationId
     * @param content
     */
    public static void createLog (DataSource ds, String relationId, String content) {
        Entity log = Entity.create("common_logs");
        log.set("relation_id", relationId);
        log.set("content", content);
        Db.insert(ds, log);
    }

	/**
	 * 验证参数合法性
	 * @param param 参数
	 * @param keys 参数必有的key
	 */
    public static void checkParam(JSONObject param, String... keys) {
    	if (keys != null && keys.length > 0) {
			Arrays.stream(keys).forEach(key -> {
				if (!param.containsKey(key)) {
					throw new HtException(key + "不能为空~");
				}
			});
    	}
	}

	public static void main(String[] args) {
		JSONObject param = JSONUtil.parseObj("""
				{
				    "param": {
				        "group_id": "GROUP_ID",
				        "group_name": "GROUP_NAME",
				        "order": 1,
				        "tag": [
				            {
				                "name": "TAG_NAME_1",
				                "order": 1
				            },
				            {
				                "name": "TAG_NAME_2",
				                "order": 2
				            }
				        ],
				        "appid": 123
				    }
				}
				""");
		
		JSONObject json = revertJson(param);
		System.err.println(json.toStringPretty());
	}
}
